#include "Cubit.h"

Cubit::Cubit(vec3 position, vec3 rotation, vec3 scale)
{
	this->position = position;
	this->rotation = rotation;
	this->scale = scale;
}

Cubit::~Cubit()
{
	Release();
}

void Cubit::Release()
{

}

void Cubit::SetPoint(int index, float x, float y, float z)
{
	if (index < 0 || index >= NUM_POINTS || points == nullptr)
	{
		std::cout << "SetPoint() index out of bounds" << std::endl;
		return;
	}

	points[index].x = x;
	points[index].y = y;
	points[index].z = z;
	points[index].w = 1;
}

void Cubit::SetAllPoints(int dim)
{
	points[0] =  vec4(0, 0, 0, 1);
	points[1] =  vec4(dim, 0, 0, 1);
	points[2] =  vec4(dim, dim, 0, 1);
	points[3] =  vec4(0, dim, 0, 1);
	points[4] =  vec4(0, 0, dim, 1);
	points[5] =  vec4(dim, 0, dim, 1);
	points[6] =  vec4(dim, dim, dim, 1);
	points[7] =  vec4(0, dim, dim, 1);
}

void Cubit::SetFace(int index, int p1, int p2, int p3, int p4, vec4 color)
{
	int i = index * 6;

	vertices[i] = points[p1]; colors[i] = color; i++;
	vertices[i] = points[p2]; colors[i] = color; i++;
	vertices[i] = points[p3]; colors[i] = color; i++;

	vertices[i] = points[p4]; colors[i] = color; i++;
	vertices[i] = points[p1]; colors[i] = color; i++;
	vertices[i] = points[p3]; colors[i] = color; i++;
}

void Cubit::SetOrigin(vec3 origin)
{
	this->origin = vec4(origin, 1);
}

void Cubit::Initialize()
{
	for (int i = 0; i < NUM_POINTS; i++)
	{
		points[i].x += origin.x;
		points[i].y += origin.y;
		points[i].z += origin.z;
	}
	
	GLuint vao;
	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glGenBuffers(1, &buffer);
	glBindBuffer(GL_ARRAY_BUFFER, buffer);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) + sizeof(colors), NULL, GL_STATIC_DRAW);
	glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
	glBufferSubData(GL_ARRAY_BUFFER, sizeof(vertices), sizeof(colors), colors);

	glUseProgram(programID);
	GLint orthoLoc = glGetUniformLocation(programID, "ortho");
	glProgramUniformMatrix4fv(programID, orthoLoc, 1, false, Ortho2D(ORTHOPROJ.x, ORTHOPROJ.y, ORTHOPROJ.z, ORTHOPROJ.w));
}

void Cubit::Render()
{
	glUseProgram(programID);
	glBindBuffer(GL_ARRAY_BUFFER, buffer);

	GLuint vPosition = glGetAttribLocation(programID, "vPosition");
	glEnableVertexAttribArray(vPosition);
	glVertexAttribPointer(vPosition, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

	GLuint vColor = glGetUniformLocation(programID, "uColor");
	//glEnableVertexAttribArray(vColor);
	//glVertexAttribPointer(vColor, 4, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(vertices)));
	glUniform4f(vColor, 1, 0, 0, 1);

	GLint worldLoc = glGetUniformLocation(programID, "world");
	glProgramUniformMatrix4fv(programID, worldLoc, 1, true, GetTransformation(position, rotation, scale));

	glDrawArrays(GL_TRIANGLES, 0, NUM_VERTS);

	glDisableVertexAttribArray(vPosition);
	glDisableVertexAttribArray(vColor);
}

mat4 Cubit::GetTransformation(vec3 translate, vec3 rotate, vec3 scale)
{
	return mat4 (vec4(scale.x * cos(rotate.y) * cos(rotate.z), -sin(rotate.z), sin(rotate.y), translate.x),
				 vec4(sin(rotate.z), scale.y * cos(rotate.x) * cos(rotate.z), -sin(rotate.x), translate.y),
				 vec4(-sin(rotate.y), sin(rotate.x), scale.z * cos(rotate.x) * cos(rotate.y), translate.z),
				 vec4(0, 0, 0, 1));
}